package com.conop.gradient;

public class BoxSet implements ConvexSet 
{
	private NDPoint _LbPnt;
	private NDPoint _UbPnt;
	private final int _dim;
	
	public BoxSet(NDPoint lbpnt, NDPoint ubpnt) throws IllegalArgumentException
	{
		if (lbpnt.getDim() != ubpnt.getDim())
			throw new IllegalArgumentException("Point dimensions must agree");
		
		_dim = lbpnt.getDim();
		
		for (int i = 0; i < _dim; i++)
			if (lbpnt.getCoordinate(i) > ubpnt.getCoordinate(i))
				throw new IllegalArgumentException("LB must be <= UB for all coordinates");
		
		_LbPnt = new NDPoint(lbpnt);
		_UbPnt = new NDPoint(ubpnt);
	}
	
	public BoxSet(double[] lbarr, double[] ubarr)
	{
		this(new NDPoint(lbarr), new NDPoint(ubarr));
	}
	
	@Override
	public boolean isFeasible(NDPoint pnt) throws IllegalArgumentException
	{
		if (pnt.getDim() != _LbPnt.getDim())
			throw new IllegalArgumentException("Point dimensions must agree");
		
		for (int i = 0; i < _dim; i++)
		{
			if (pnt.getCoordinate(i) < _LbPnt.getCoordinate(i) ||
				pnt.getCoordinate(i) > _UbPnt.getCoordinate(i)	)
				return false;
		}
		
		return true;
	}

	@Override
	public NDPoint Projection(NDPoint pnt) throws IllegalArgumentException 
	{
		if (pnt.getDim() != _dim)
			throw new IllegalArgumentException("Point dimensions must agree");
		
		double[] arr = new double[_dim];
		
		for (int i = 0; i < _dim; i++)
		{
			arr[i] = Math.max(Math.min(pnt.getCoordinate(i), _UbPnt.getCoordinate(i)), _LbPnt.getCoordinate(i));
		}
		
		return new NDPoint(arr);
	}
	
	@Override
	public String toString()
	{
		StringBuilder sb = new StringBuilder("Box set: \n");
		
		for (int i = 0; i < _dim; i++)
		{
			sb.append("\t").append(_LbPnt.getCoordinate(i)).append("<=")
			  .append(" x").append(i).append(" <= ").append(_UbPnt.getCoordinate(i)).append("\n");
		}
		
		return sb.toString();
	}
}
